/**
 * Copyright (c) 2010, Todd Ginsberg
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the name of Todd Ginsberg, or Gowalla nor the
 *      names of any contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 *  Also, please use this for Good and not Evil.  
 */
package com.ginsberg.gowalla.dto;

import java.util.List;

/**
 * Full information about a Gowalla User.
 * Please note that some fields are not populated by Gowalla unless the currently
 * authenticated user asks for their own data.  These accessors have been documented,
 * please read the JavaDoc to be sure you aren't just using a default for these
 * cases, if your application depends on it.
 * 
 * @author Todd Ginsberg
 */
public class FullUser extends User {

	private static final long serialVersionUID = -251157891351625343L;
	private String bio;
	private int friends_count;
	private boolean _is_friend;
	private int items_count;
	private int pins_count;
	private int stamps_count;
	private String twitter_username;
	private String facebook_id;
	private String website;
	private int photos_count;
	private int _street_team_level;
	private int _checkin_radius_meters;
	private List<UserEvent> last_checkins;
	private boolean can_post_to_twitter;
	private boolean can_post_to_facebook;
	private int bookmarked_spots_count;
	private String _image_url_200;
	private int trips_count; 
	private List<Id<Spot>> currentCheckins;
	private int highlights_count;
	private String twitter_id;
	
	/**
	 * 
	 */
	public FullUser() {
		super();
	}

	/**
	 * NOTE: Gowalla only populates this when you request
	 * the currently authenticated user.  Therefore, we 
	 * default this to false, to err on the side of caution
	 * when we don't receive this value.
	 */
	public boolean getCanPostToTwitter() {
		return can_post_to_twitter;
	}

	public void setCanPostToTwitter(boolean canPostToTwitter) {
		can_post_to_twitter = canPostToTwitter;
	}

	/**
	 * NOTE: Gowalla only populates this when you request
	 * the currently authenticated user.  Therefore, we 
	 * default this to false, to err on the side of caution
	 * when we don't receive this value.
	 */
	public boolean getCanPostToFacebook() {
		return can_post_to_facebook;
	}

	public void setCanPostToFacebook(boolean canPostToFacebook) {
		can_post_to_facebook = canPostToFacebook;
	}

	/**
	 * NOTE: Gowalla only populates this when you request
	 * the currently authenticated user.  Therefore, we 
	 * default this to zero when we don't receive it.  
	 * Since we don't have a clear understanding of 
	 * the values (STE members appear to be "1"), please 
	 * act carefully with this data. 
	 */
	public int getStreetTeamLevel() {
		return _street_team_level;
	}

	public void setStreetTeamLevel(int streetTeamLevel) {
		_street_team_level = streetTeamLevel;
	}

	/**
	 * NOTE: Gowalla only populates this when you request
	 * the currently authenticated user.  Therefore, we 
	 * default this to 0 to be safe when we don't receive it.
	 */
	public int getCheckinRadiusMeters() {
		return _checkin_radius_meters;
	}

	public void setCheckinRadiusMeters(int checkinRadiusMeters) {
		_checkin_radius_meters = checkinRadiusMeters;
	}

	public String getBio() {
		return bio;
	}

	public void setBio(String bio) {
		this.bio = bio;
	}

	public int getFriends_count() {
		return friends_count;
	}

	public void setFriendsCount(int friendsCount) {
		this.friends_count = friendsCount;
	}

	public boolean isFriend() {
		return _is_friend;
	}

	public void setFriend(boolean isFiend) {
		this._is_friend = isFiend;
	}

	public int getItemsCount() {
		return items_count;
	}

	public void setItemsCount(int itemsCount) {
		this.items_count = itemsCount;
	}

	public int getPinsCount() {
		return pins_count;
	}

	public void setPinsCount(int pinsCount) {
		this.pins_count = pinsCount;
	}

	public int getStampsCount() {
		return stamps_count;
	}

	public void setStampsCount(int stampsCount) {
		this.stamps_count = stampsCount;
	}

	public String getImageUrl200() {
		return _image_url_200;
	}

	public void setImageUrl200(String _image_url_200) {
		this._image_url_200 = _image_url_200;
	}
	
	public String getImageUrl() {
		return image_url;
	}

	public void setImageUrl(String imageUrl) {
		this.image_url = imageUrl;
	}

	public String getTwitterUsername() {
		return twitter_username;
	}

	public void setTwitterUsername(String twitterUsername) {
		this.twitter_username = twitterUsername;
	}

	public String getFacebookId() {
		return facebook_id;
	}

	public void setFacebookId(String facebookId) {
		this.facebook_id = facebookId;
	}

	public String getWebsite() {
		return website;
	}

	public void setWebsite(String website) {
		this.website = website;
	}

	public List<UserEvent> getLastCheckins() {
		return last_checkins;
	}

	public void setLastCheckins(List<UserEvent> lastCheckins) {
		this.last_checkins = lastCheckins;
	}

	public int getTripsCount() {
		return trips_count;
	}

	public void setTripsCount(int trips_count) {
		this.trips_count = trips_count;
	}
	
	public int getBookmarkedSpotCount() {
		return bookmarked_spots_count;
	}

	public void setBookmarkedSpotCount(int bookmarked_spots_count) {
		this.bookmarked_spots_count = bookmarked_spots_count;
	}
	
	public int getPhotosCount() {
		return photos_count;
	}

	public void setPhotosCount(int photosCount) {
		this.photos_count = photosCount;
	}

	/**
	 * Only available when the user is the one performing
	 * the authentication.  Meaning you can't currently see
	 * what your friend's current checkins are unless you
	 * auth as them.  If this returns null, it means the data
	 * is not available.  If it returns an empty List, it means
	 * that the data was available but there are no current
	 * checkins.
	 */
	public List<Id<Spot>> getCurrentCheckins() {
		return currentCheckins;
	}

	/**
	 * @param currentCheckins the currentCheckins to set
	 */
	public void setCurrentCheckins(List<Id<Spot>> currentCheckins) {
		this.currentCheckins = currentCheckins;
	}

	/**
	 * Get the most recent checkin from a potential array of checkins
	 * Gowalla returns.  
	 * 
	 * Note: This might have to change, I've not seen the API return more
	 * than one of these, so I'm guessing they'll be in order.
	 * 
	 * @return A UserEvent object
	 */
	public UserEvent getLastCheckin() {
		return last_checkins == null || last_checkins.size() == 0 ? null : last_checkins.get(0);
	}

	/**
	 * Only available for currently checked in user.
	 * @return the highlights_count
	 */
	public int getHighlightsCount() {
		return highlights_count;
	}

	/**
	 * @param highlightsCount the highlights_count to set
	 */
	public void setHighlightsCount(int highlightsCount) {
		highlights_count = highlightsCount;
	}

	/**
	 * @return the twitter_id
	 */
	public String getTwitterId() {
		return twitter_id;
	}

	/**
	 * @param twitterId the twitter_id to set
	 */
	public void setTwitterId(String twitterId) {
		twitter_id = twitterId;
	}

	/**
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		result = prime * result + _checkin_radius_meters;
		result = prime * result
				+ ((_image_url_200 == null) ? 0 : _image_url_200.hashCode());
		result = prime * result + (_is_friend ? 1231 : 1237);
		result = prime * result + _street_team_level;
		result = prime * result + ((bio == null) ? 0 : bio.hashCode());
		result = prime * result + bookmarked_spots_count;
		result = prime * result + (can_post_to_facebook ? 1231 : 1237);
		result = prime * result + (can_post_to_twitter ? 1231 : 1237);
		result = prime * result
				+ ((currentCheckins == null) ? 0 : currentCheckins.hashCode());
		result = prime * result
				+ ((facebook_id == null) ? 0 : facebook_id.hashCode());
		result = prime * result + friends_count;
		result = prime * result + highlights_count;
		result = prime * result + items_count;
		result = prime * result
				+ ((last_checkins == null) ? 0 : last_checkins.hashCode());
		result = prime * result + photos_count;
		result = prime * result + pins_count;
		result = prime * result + stamps_count;
		result = prime * result + trips_count;
		result = prime * result
				+ ((twitter_id == null) ? 0 : twitter_id.hashCode());
		result = prime
				* result
				+ ((twitter_username == null) ? 0 : twitter_username.hashCode());
		result = prime * result + ((website == null) ? 0 : website.hashCode());
		return result;
	}

	/**
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		FullUser other = (FullUser) obj;
		if (_checkin_radius_meters != other._checkin_radius_meters)
			return false;
		if (_image_url_200 == null) {
			if (other._image_url_200 != null)
				return false;
		} else if (!_image_url_200.equals(other._image_url_200))
			return false;
		if (_is_friend != other._is_friend)
			return false;
		if (_street_team_level != other._street_team_level)
			return false;
		if (bio == null) {
			if (other.bio != null)
				return false;
		} else if (!bio.equals(other.bio))
			return false;
		if (bookmarked_spots_count != other.bookmarked_spots_count)
			return false;
		if (can_post_to_facebook != other.can_post_to_facebook)
			return false;
		if (can_post_to_twitter != other.can_post_to_twitter)
			return false;
		if (currentCheckins == null) {
			if (other.currentCheckins != null)
				return false;
		} else if (!currentCheckins.equals(other.currentCheckins))
			return false;
		if (facebook_id == null) {
			if (other.facebook_id != null)
				return false;
		} else if (!facebook_id.equals(other.facebook_id))
			return false;
		if (friends_count != other.friends_count)
			return false;
		if (highlights_count != other.highlights_count)
			return false;
		if (items_count != other.items_count)
			return false;
		if (last_checkins == null) {
			if (other.last_checkins != null)
				return false;
		} else if (!last_checkins.equals(other.last_checkins))
			return false;
		if (photos_count != other.photos_count)
			return false;
		if (pins_count != other.pins_count)
			return false;
		if (stamps_count != other.stamps_count)
			return false;
		if (trips_count != other.trips_count)
			return false;
		if (twitter_id == null) {
			if (other.twitter_id != null)
				return false;
		} else if (!twitter_id.equals(other.twitter_id))
			return false;
		if (twitter_username == null) {
			if (other.twitter_username != null)
				return false;
		} else if (!twitter_username.equals(other.twitter_username))
			return false;
		if (website == null) {
			if (other.website != null)
				return false;
		} else if (!website.equals(other.website))
			return false;
		return true;
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return String
				.format(
						"FullUser [_checkin_radius_meters=%s, _image_url_200=%s, _is_friend=%s, _street_team_level=%s, bio=%s, bookmarked_spots_count=%s, can_post_to_facebook=%s, can_post_to_twitter=%s, currentCheckins=%s, facebook_id=%s, friends_count=%s, highlights_count=%s, items_count=%s, last_checkins=%s, photos_count=%s, pins_count=%s, stamps_count=%s, trips_count=%s, twitter_id=%s, twitter_username=%s, website=%s]",
						_checkin_radius_meters, _image_url_200, _is_friend,
						_street_team_level, bio, bookmarked_spots_count,
						can_post_to_facebook, can_post_to_twitter,
						currentCheckins, facebook_id, friends_count,
						highlights_count, items_count, last_checkins,
						photos_count, pins_count, stamps_count, trips_count,
						twitter_id, twitter_username, website);
	}
}
